package game.objects;
import java.util.ArrayList;
import java.util.Vector;

import org.w3c.dom.Document;

import editors.objectedit.BoundingBox;
import editors.objectedit.LoadObject;
import editors.objectedit.SaveObject;

import physics.Body;

import game.Game;
import graphics.objects.GraphicsObject;
import tools.Floatmath;
import tools.Help;
import tools.Point;
import tools.intersectionTests.IntersectionTest;
public class GODynamic extends GameObject {
	private class PState {
		public Point pos;
		public float apos;
		public PState(Point pos, float apos) {
			this.pos = pos;
			this.apos = apos;
		}
	}
	private ArrayList<PState> states;
	private Document copydoc;
	private Point copycenter;
	public GODynamic(Game g, Point pos, float angle, float scale) {
		super(g, pos, angle, scale);
		states = new ArrayList<PState>();
	}
	public GODynamic(Game g) {
		super(g, new Point(), 0, 1);
	}
	@Override
	public void handle() {
	}
	public void saveFile(String fileName) {
		SaveObject.save(fileName, this);
	}
	public void initialize(Point pos, float apos, float s) {
		states = new ArrayList<PState>();
	}
	public void loadFile(String fileName, BoundingBox b) {
		try {
			LoadObject.load(fileName, this, b);
			updateBodies();
		} catch (Exception e) {
			Help.p(e.getStackTrace());
		}
	}
	public void saveLoadPhysicState() {
		if (!game.engine.isDophysics()) {
			states.clear();
			for (int i = 0; i < this.numBodies; i++) {
				states.add(new PState(new Point(getBody(i).pos), getBody(i).apos));
			}
		}
		else {
			for (int i = 0; i < this.numBodies; i++) {
				if (i < states.size()) {
					getBody(i).pos = states.get(i).pos;
					getBody(i).apos = states.get(i).apos;
					getBody(i).wakeUp();
					getBody(i).stop();
					getBody(i).update(0);
				}
			}
			for (int i = 0; i < numJoints; i++) {
				getJoint(i).calcPositionOffsets();
			}
		}
	}
	public Body getBodyAt(Point pos) {
		Body f = null;
		for (int i = 0; i < this.numBodies; i++) {
			if (IntersectionTest.intersects(pos, getBody(i).shape)) {
				f = getBody(i);
			}
		}
		return f;
	}
	public GraphicsObject getGROAt(Point pos) {
		GraphicsObject gro = null;
		float mindist = Float.POSITIVE_INFINITY;
		for (int i = 0; i < this.numGraphicsObjects; i++) {
			if (pos.distance(getGraphicsObject(i).node.pos) < getGraphicsObject(i).node.boundingrad && pos.distance(getGraphicsObject(i).node.pos) < mindist) {
				gro = getGraphicsObject(i);
				mindist = pos.distance(getGraphicsObject(i).node.pos);
			}
		}
		return gro;
	}
	public void loadFile(String fileName, Point pos) {
		try {
			LoadObject.load(fileName, this, pos);
			updateBodies();
		} catch (Exception e) {
			Help.p(e.getStackTrace());
		}
	}
	public void updateBodies() {
		for (int i = 0; i < numBodies; i++) {
			getBody(i).update(0);
		}
	}
	public void clear() {
		while (this.numBodies > 0)
			this.remBodyWithGraphics(getBody(0));
		while (this.numJoints > 0)
			this.remJoint(getJoint(0));
		while (this.numGraphicsObjects > 0)
			this.remGraphicsObject(getGraphicsObject(0));
	}
	public ArrayList<Body> getBodiesInRect(Point p0, Point p1) {
		float x = Floatmath.min(p0.x, p1.x);
		float y = Floatmath.min(p0.y, p1.y);
		float X = Floatmath.max(p0.x, p1.x);
		float Y = Floatmath.max(p0.y, p1.y);
		ArrayList<Body> sb = new ArrayList<Body>();
		for (int i = 0; i < this.numBodies; i++) {
			Body b = getBody(i);
			if (b.pos.x > x && b.pos.x < X && b.pos.y > y && b.pos.y < Y) {
				sb.add(b);
			}
		}
		return sb;
	}
	public ArrayList<GraphicsObject> getGROsInRect(Point p0, Point p1) {
		float x = Floatmath.min(p0.x, p1.x);
		float y = Floatmath.min(p0.y, p1.y);
		float X = Floatmath.max(p0.x, p1.x);
		float Y = Floatmath.max(p0.y, p1.y);
		ArrayList<GraphicsObject> sg = new ArrayList<GraphicsObject>();
		for (int i = 0; i < this.numGraphicsObjects; i++) {
			GraphicsObject g = getGraphicsObject(i);
			if (g.node.pos.x > x && g.node.pos.x < X && g.node.pos.y > y && g.node.pos.y < Y) {
				sg.add(g);
			}
		}
		return sg;
	}
	public Body getBodyAt(Point pos, Body ignorebody) {
		Body f = null;
		for (int i = 0; i < this.numBodies; i++) {
			if (getBody(i).id != ignorebody.id && IntersectionTest.intersects(pos, getBody(i).shape)) {
				f = getBody(i);
			}
		}
		return f;
	}
	public void copy(Vector<Body> bodies, Vector<GraphicsObject> gros) {
		try{
			this.copydoc = SaveObject.saveCopy(this, bodies, gros);
			this.copycenter = SaveObject.center;
		}catch(Exception e)
		{
			Help.p(e.getLocalizedMessage());
		}
	}

	public void paste(Point p){
		try{
			if(this.copydoc != null){
				LoadObject.loadCopy(copydoc, this, p.sub(copycenter));
				updateBodies();
			}
		}catch(Exception e){
			Help.p(e.getLocalizedMessage());
		}
	}

	public BoundingBox getBoundinboxBodies() {
		Vector<Body> bodies = new Vector<Body>();
		for (int i = 0; i < numBodies; i++) {
			bodies.add(getBody(i));
		}
		return new BoundingBox(bodies, new Vector<GraphicsObject>());
	}
}
